home *** CD-ROM | disk | FTP | other *** search
- /* X-specific Lisp objects.
- Copyright (C) 1993, 1994 Free Software Foundation, Inc.
- Copyright (C) 1995 Board of Trustees, University of Illinois
- Copyright (C) 1995 Tinker Systems
- Copyright (C) 1995 Ben Wing
- Copyright (C) 1995 Sun Microsystems
-
- This file is part of XEmacs.
-
- XEmacs is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by the
- Free Software Foundation; either version 2, or (at your option) any
- later version.
-
- XEmacs is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- for more details.
-
- You should have received a copy of the GNU General Public License
- along with XEmacs; see the file COPYING. If not, write to the Free
- Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-
- /* Synched up with: Not in FSF. */
-
- /* Original author: Jamie Zawinski for 19.8
- font-truename stuff added by Jamie Zawinski for 19.10
- subwindow support added by Chuck Thompson
- additional XPM support added by Chuck Thompson
- initial X-Face support added by Stig
- rewritten/restructured by Ben Wing for 19.12/19.13
- */
-
- #include <config.h>
- #include "lisp.h"
-
- #include "device-x.h"
- #include "frame-x.h"
- #include "glyphs-x.h"
- #include "objects-x.h"
- #include "xmu.h"
-
- #include "buffer.h"
- #include "insdel.h"
-
- #include "sysfile.h"
-
- /* #### This isn't going to be sufficient if we ever want to handle
- multiple screens on a single display. */
- #define LISP_DEVICE_TO_X_SCREEN(dev) \
- XDefaultScreenOfDisplay (DEVICE_X_DISPLAY (XDEVICE (dev)))
-
- DEFINE_IMAGE_INSTANTIATOR_TYPE (xbm);
- Lisp_Object Qxbm;
-
- Lisp_Object Q_mask_file, Q_mask_data, Q_hotspot_x, Q_hotspot_y;
- Lisp_Object Q_foreground, Q_background;
-
- #ifdef HAVE_XPM
- DEFINE_IMAGE_INSTANTIATOR_TYPE (xpm);
- Lisp_Object Qxpm;
- Lisp_Object Q_color_symbols;
- #endif
-
- #ifdef HAVE_XFACE
- DEFINE_IMAGE_INSTANTIATOR_TYPE (xface);
- Lisp_Object Qxface;
- #endif
-
- #ifdef HAVE_JPEG
- DEFINE_IMAGE_INSTANTIATOR_TYPE (jpeg);
- Lisp_Object Qjpeg;
- #endif
-
- #ifdef HAVE_PNG
- DEFINE_IMAGE_INSTANTIATOR_TYPE (png);
- Lisp_Object Qpng;
- #endif
-
- #ifdef HAVE_GIF
- DEFINE_IMAGE_INSTANTIATOR_TYPE (gif);
- Lisp_Object Qgif;
- #endif
-
- DEFINE_IMAGE_INSTANTIATOR_TYPE (autodetect);
- Lisp_Object Qautodetect;
-
- #include "bitmaps.h"
-
-
- /************************************************************************/
- /* image instance methods */
- /************************************************************************/
-
- static void
- x_print_image_instance (struct Lisp_Image_Instance *p,
- Lisp_Object printcharfun,
- int escapeflag)
- {
- char buf[100];
-
- switch (IMAGE_INSTANCE_TYPE (p))
- {
- case IMAGE_MONO_PIXMAP:
- case IMAGE_COLOR_PIXMAP:
- case IMAGE_CURSOR:
- sprintf (buf, " (0x%lx", (unsigned long) IMAGE_INSTANCE_X_PIXMAP (p));
- write_c_string (buf, printcharfun);
- if (IMAGE_INSTANCE_X_MASK (p))
- {
- sprintf (buf, "/0x%lx", (unsigned long) IMAGE_INSTANCE_X_MASK (p));
- write_c_string (buf, printcharfun);
- }
- write_c_string (")", printcharfun);
- break;
- case IMAGE_SUBWINDOW:
- /* #### implement me */
- default:
- break;
- }
- }
-
- static void
- x_finalize_image_instance (struct Lisp_Image_Instance *p)
- {
- Screen *scr = LISP_DEVICE_TO_X_SCREEN (IMAGE_INSTANCE_DEVICE (p));
-
- if (!p->data)
- return;
-
- if (IMAGE_INSTANCE_X_PIXMAP (p))
- XFreePixmap (DisplayOfScreen (scr), IMAGE_INSTANCE_X_PIXMAP (p));
- if (IMAGE_INSTANCE_X_MASK (p) &&
- IMAGE_INSTANCE_X_MASK (p) != IMAGE_INSTANCE_X_PIXMAP (p))
- XFreePixmap (DisplayOfScreen (scr), IMAGE_INSTANCE_X_MASK (p));
- IMAGE_INSTANCE_X_PIXMAP (p) = 0;
- IMAGE_INSTANCE_X_MASK (p) = 0;
-
- if (IMAGE_INSTANCE_X_CURSOR (p))
- {
- XFreeCursor (DisplayOfScreen (scr), IMAGE_INSTANCE_X_CURSOR (p));
- IMAGE_INSTANCE_X_CURSOR (p) = 0;
- }
-
- if (IMAGE_INSTANCE_X_NPIXELS (p) != 0)
- {
- XFreeColors (DisplayOfScreen (scr),
- DefaultColormapOfScreen (scr),
- IMAGE_INSTANCE_X_PIXELS (p),
- IMAGE_INSTANCE_X_NPIXELS (p), 0);
- IMAGE_INSTANCE_X_NPIXELS (p) = 0;
- }
- if (IMAGE_INSTANCE_X_PIXELS (p))
- {
- xfree (IMAGE_INSTANCE_X_PIXELS (p));
- IMAGE_INSTANCE_X_PIXELS (p) = 0;
- }
-
- xfree (p->data);
- p->data = 0;
- }
-
- static int
- x_image_instance_equal (struct Lisp_Image_Instance *p1,
- struct Lisp_Image_Instance *p2, int depth)
- {
- switch (IMAGE_INSTANCE_TYPE (p1))
- {
- case IMAGE_MONO_PIXMAP:
- case IMAGE_COLOR_PIXMAP:
- case IMAGE_CURSOR:
- if (IMAGE_INSTANCE_X_NPIXELS (p1) != IMAGE_INSTANCE_X_NPIXELS (p2))
- return 0;
- break;
- case IMAGE_SUBWINDOW:
- /* #### implement me */
- break;
- default:
- break;
- }
-
- return 1;
- }
-
- static unsigned long
- x_image_instance_hash (struct Lisp_Image_Instance *p, int depth)
- {
- switch (IMAGE_INSTANCE_TYPE (p))
- {
- case IMAGE_MONO_PIXMAP:
- case IMAGE_COLOR_PIXMAP:
- case IMAGE_CURSOR:
- return IMAGE_INSTANCE_X_NPIXELS (p);
- case IMAGE_SUBWINDOW:
- /* #### implement me */
- return 0;
- default:
- return 0;
- }
- }
-
-
- /************************************************************************/
- /* image instance utility functions */
- /************************************************************************/
-
- /* Where bitmaps are; initialized from resource database */
- Lisp_Object Vx_bitmap_file_path;
-
- #ifndef BITMAPDIR
- #define BITMAPDIR "/usr/include/X11/bitmaps"
- #endif
-
- #define USE_XBMLANGPATH
-
- /* Given a pixmap filename, look through all of the "standard" places
- where the file might be located. Return a full pathname if found;
- otherwise, return Qnil. */
-
- static Lisp_Object
- locate_pixmap_file (Lisp_Object name)
- {
- /* This function can GC if IN_REDISPLAY is false */
- Display *display;
-
- /* Check non-absolute pathnames with a directory component relative to
- the search path; that's the way Xt does it. */
- /* #### Unix-specific */
- if (string_byte (XSTRING (name), 0) == '/' ||
- (string_byte (XSTRING (name), 0) == '.' &&
- (string_byte (XSTRING (name), 1) == '/' ||
- (string_byte (XSTRING (name), 1) == '.' &&
- (string_byte (XSTRING (name), 2) == '/')))))
- {
- if (!NILP (Ffile_readable_p (name)))
- return name;
- else
- return Qnil;
- }
-
- if (NILP (Vdefault_x_device))
- /* This may occur during intialization. */
- return Qnil;
- else
- /* We only check the bitmapFilePath resource on the original X device. */
- display = DEVICE_X_DISPLAY (XDEVICE (Vdefault_x_device));
-
- #ifdef USE_XBMLANGPATH
- {
- char *path = egetenv ("XBMLANGPATH");
- SubstitutionRec subs[1];
- subs[0].match = 'B';
- subs[0].substitution = (char *) string_data (XSTRING (name));
- /* #### Motif uses a big hairy default if $XBMLANGPATH isn't set.
- We don't. If you want it used, set it. */
- if (path &&
- (path = XtResolvePathname (display, "bitmaps", 0, 0, path,
- subs, XtNumber (subs), 0)))
- {
- name = build_string (path);
- XtFree (path);
- return (name);
- }
- }
- #endif
-
- if (NILP (Vx_bitmap_file_path))
- {
- char *type = 0;
- XrmValue value;
- if (XrmGetResource (XtDatabase (display),
- "bitmapFilePath", "BitmapFilePath", &type, &value)
- && !strcmp (type, "String"))
- Vx_bitmap_file_path = decode_env_path (0, (char *) value.addr);
- Vx_bitmap_file_path = nconc2 (Vx_bitmap_file_path,
- (list1 (build_string (BITMAPDIR))));
- }
-
- {
- Lisp_Object found;
- if (locate_file (Vx_bitmap_file_path, name, "", &found, R_OK) < 0)
- {
- Lisp_Object temp = list1 (Vdata_directory);
- struct gcpro gcpro1;
-
- GCPRO1 (temp);
- locate_file (temp, name, "", &found, R_OK);
- UNGCPRO;
- }
-
- return found;
- }
- }
-
- /* If INST refers to inline data, return Qnil.
- If INST refers to data in a file, return the full filename
- if it exists; otherwise, return t. */
-
- static Lisp_Object
- potential_pixmap_file_instantiator (Lisp_Object inst,
- Lisp_Object file_keyword,
- Lisp_Object data_keyword)
- {
- Lisp_Object file;
- Lisp_Object data;
-
- assert (VECTORP (inst));
-
- data = find_keyword_in_vector (inst, data_keyword);
- file = find_keyword_in_vector (inst, file_keyword);
-
- if (!NILP (file) && NILP (data))
- {
- Lisp_Object retval = locate_pixmap_file (file);
- if (!NILP (retval))
- return retval;
- else
- return Qt; /* should have been file */
- }
-
- return Qnil;
- }
-
- static void
- x_initialize_pixmap_image_instance (struct Lisp_Image_Instance *ii)
- {
- ii->data = malloc_type_and_zero (struct x_image_instance_data);
- IMAGE_INSTANCE_TYPE (ii) = IMAGE_MONO_PIXMAP;
- IMAGE_INSTANCE_PIXMAP_FILENAME (ii) = Qnil;
- IMAGE_INSTANCE_PIXMAP_MASK_FILENAME (ii) = Qnil;
- IMAGE_INSTANCE_PIXMAP_WIDTH (ii) = 0;
- IMAGE_INSTANCE_PIXMAP_HEIGHT (ii) = 0;
- IMAGE_INSTANCE_PIXMAP_DEPTH (ii) = 0;
- IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii) = Qnil;
- IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii) = Qnil;
- }
-
- /* Check that this server supports cursors of this size. */
- static int
- check_pointer_sizes (Screen *xs, unsigned int width, unsigned int height,
- Lisp_Object instantiator, int no_error)
- {
- unsigned int best_width, best_height;
- if (! XQueryBestCursor (DisplayOfScreen (xs), RootWindowOfScreen (xs),
- width, height, &best_width, &best_height))
- /* #### What does it mean when XQueryBestCursor() returns 0?
- I can't find that documented anywhere. */
- best_width = best_height = 0;
-
- if (width > best_width || height > best_height)
- {
- if (!no_error)
- {
- char buf [255];
- sprintf (buf, "cursor too large (%dx%d): "
- "server requires %dx%d or smaller",
- width, height, best_width, best_height);
- signal_error (Qerror, list2 (build_string (buf), instantiator));
- }
- return 0;
- }
-
- return 1;
- }
-
-
- /**********************************************************************
- * XBM *
- **********************************************************************/
-
- /* Check if DATA represents a valid inline XBM spec (i.e. a cons
- of (width height bits), with checking done on the dimensions).
- If so, return 1. If not, return 0 if NO_ERROR is non-zero;
- otherwise, signal an error. */
-
- static int
- valid_xbm_inline_p (Lisp_Object data, int no_error)
- {
- Lisp_Object width, height, bits;
-
- if (!CONSP (data))
- {
- if (!no_error)
- CHECK_CONS (data, 0);
- return 0;
- }
- if (!CONSP (XCDR (data)) || !CONSP (XCDR (XCDR (data))) ||
- !NILP (XCDR (XCDR (XCDR (data)))))
- {
- if (!no_error)
- signal_simple_error ("Must be list of 3 elements", data);
- return 0;
- }
-
- width = XCAR (data);
- height = XCAR (XCDR (data));
- bits = XCAR (XCDR (XCDR (data)));
-
- if (!INTP (width) || !INTP (height) || !STRINGP (bits))
- {
- if (!no_error)
- signal_simple_error ("Must be (width height bits)",
- vector3 (width, height, bits));
- return 0;
- }
-
- if (XINT (width) <= 0)
- {
- if (!no_error)
- signal_simple_error ("Width must be > 0", width);
- return 0;
- }
-
- if (XINT (height) <= 0)
- {
- if (!no_error)
- signal_simple_error ("Height must be > 0", height);
- return 0;
- }
-
- if (((unsigned) (XINT (width) * XINT (height)) / 8)
- > string_length (XSTRING (bits)))
- {
- if (!no_error)
- signal_simple_error ("data is too short for W and H",
- vector3 (width, height, bits));
- return 0;
- }
-
- return 1;
- }
-
- /* Validate method for XBM's. */
-
- static int
- xbm_validate (Lisp_Object instantiator, int no_error)
- {
- return file_or_data_must_be_present (instantiator, no_error);
- }
-
- /* Given a filename that is supposed to contain XBM data, return
- the inline representation of it as (width height bits). Return
- the hotspot through XHOT and YHOT, if those pointers are not 0.
- If there is no hotspot, XHOT and YHOT will contain -1.
-
- If the function fails:
-
- -- if OK_IF_DATA_INVALID is set and the data was invalid,
- return Qt.
- -- if NO_ERROR is set, return Qnil.
- -- otherwise, signal an error.
- */
-
-
- static Lisp_Object
- bitmap_to_lisp_data (Lisp_Object name, int *xhot, int *yhot, int no_error,
- int ok_if_data_invalid)
- {
- unsigned int w, h;
- Bufbyte *data;
- int result;
-
- result = XmuReadBitmapDataFromFile ((char *) string_data (XSTRING (name)),
- &w, &h, &data, xhot, yhot);
-
- if (result == BitmapSuccess)
- {
- Lisp_Object retval;
- int len = (w + 7) / 8 * h;
-
- retval = list3 (make_number (w), make_number (h),
- make_string (data, len));
- XFree ((char *) data);
- return retval;
- }
-
- switch (result)
- {
- case BitmapOpenFailed:
- {
- if (!no_error)
- /* should never happen */
- signal_double_file_error ("Opening bitmap file",
- "no such file or directory",
- name);
- break;
- }
- case BitmapFileInvalid:
- {
- if (ok_if_data_invalid)
- return Qt;
- if (!no_error)
- signal_double_file_error ("Reading bitmap file",
- "invalid data in file",
- name);
- break;
- }
- case BitmapNoMemory:
- {
- if (!no_error)
- signal_double_file_error ("Reading bitmap file",
- "out of memory",
- name);
- break;
- }
- default:
- {
- if (!no_error)
- signal_double_file_error_2 ("Reading bitmap file",
- "unknown error code",
- make_number (result), name);
- break;
- }
- }
-
- return Qnil;
- }
-
- /* Normalize method for XBM's. */
-
- static Lisp_Object
- xbm_normalize (Lisp_Object inst, Lisp_Object device_type, int no_error)
- {
- Lisp_Object file = Qnil, mask_file = Qnil;
- struct gcpro gcpro1, gcpro2, gcpro3;
- Lisp_Object alist = Qnil;
-
- GCPRO3 (file, mask_file, alist);
-
- /* Now, convert any file data into inline data for both the regular
- data and the mask data. At the end of this, `data' will contain
- the inline data (if any) or Qnil, and `file' will contain
- the name this data was derived from (if known) or Qnil.
- Likewise for `mask_file' and `mask_data'.
-
- Note that if we cannot generate any regular inline data, we
- skip out. */
-
- file = potential_pixmap_file_instantiator (inst, Q_file, Q_data);
- mask_file = potential_pixmap_file_instantiator (inst, Q_mask_file,
- Q_mask_data);
-
- if (EQ (file, Qt)) /* failure locating filename */
- {
- if (!no_error)
- signal_double_file_error ("Opening bitmap file",
- "no such file or directory",
- file);
- RETURN_UNGCPRO (Qnil);
- }
-
- if (NILP (file) && NILP (mask_file)) /* no conversion necessary */
- RETURN_UNGCPRO (inst);
-
- alist = tagged_vector_to_alist (inst);
-
- if (!NILP (file))
- {
- int xhot, yhot;
- Lisp_Object data = bitmap_to_lisp_data (file, &xhot, &yhot, no_error, 0);
- if (NILP (data)) /* conversion failure; error should
- already be signalled. */
- RETURN_UNGCPRO (Qnil);
- alist = remassq_no_quit (Q_file, alist);
- /* there can't be a :data at this point. */
- alist = Fcons (Fcons (Q_file, file),
- Fcons (Fcons (Q_data, data), alist));
-
- if (xhot != -1 && NILP (assq_no_quit (Q_hotspot_x, alist)))
- alist = Fcons (Fcons (Q_hotspot_x, make_number (xhot)),
- alist);
- if (yhot != -1 && NILP (assq_no_quit (Q_hotspot_y, alist)))
- alist = Fcons (Fcons (Q_hotspot_y, make_number (yhot)),
- alist);
- }
-
- if (!NILP (mask_file))
- {
- Lisp_Object mask_data =
- bitmap_to_lisp_data (mask_file, 0, 0, no_error, 0);
- alist = remassq_no_quit (Q_mask_file, alist);
- /* there can't be a :mask-data at this point. */
- alist = Fcons (Fcons (Q_mask_file, mask_file),
- Fcons (Fcons (Q_mask_data, mask_data), alist));
- }
-
- {
- Lisp_Object result = alist_to_tagged_vector (Qxbm, alist);
- free_alist (alist);
- RETURN_UNGCPRO (result);
- }
- }
-
- /* Given inline data for a mono pixmap, create and return the
- corresponding X object. */
-
- static Pixmap
- pixmap_from_xbm_inline (Lisp_Object device, int width, int height,
- char *bits)
- {
- Screen *screen = LISP_DEVICE_TO_X_SCREEN (device);
- return XCreatePixmapFromBitmapData (DisplayOfScreen (screen),
- RootWindowOfScreen (screen),
- bits, width, height,
- 1, 0, 1);
- }
-
- /* Given inline data for a mono pixmap, initialize the given
- image instance accordingly. */
-
- static int
- init_image_instance_from_xbm_inline (struct Lisp_Image_Instance *ii,
- int width, int height,
- unsigned char *bits,
- Lisp_Object instantiator,
- int dest_mask,
- Pixmap mask,
- Lisp_Object mask_filename,
- int no_error)
- {
- Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
- Lisp_Object foreground = find_keyword_in_vector (instantiator, Q_foreground);
- Lisp_Object background = find_keyword_in_vector (instantiator, Q_background);
- Display *dpy = DEVICE_X_DISPLAY (XDEVICE (device));
- Screen *scr = DefaultScreenOfDisplay (dpy);
- int free_count = 0;
- unsigned long pixels_to_free[2];
- enum image_instance_type type;
-
- /* #### Hey Ben! Something is really screwy here. It is possible
- to get in here with dest_mask == ~0 (anything). Even in a case
- like this:
-
- [xbm :file "/foo/bar/baz"]
-
- and in that case this used to pick it up as a cursor because that
- was the first check. Way bogus. For now I've moved the cursor
- check to the end. I think that maybe there should be some
- additional checks being made about setting dest_mask somewhere up
- the call chain, though. */
-
- if ((dest_mask & IMAGE_MONO_PIXMAP_MASK) &&
- (dest_mask & IMAGE_COLOR_PIXMAP_MASK))
- {
- if (!NILP (foreground) || !NILP (background))
- type = IMAGE_COLOR_PIXMAP;
- else
- type = IMAGE_MONO_PIXMAP;
- }
- else if (dest_mask & IMAGE_MONO_PIXMAP_MASK)
- type = IMAGE_MONO_PIXMAP;
- else if (dest_mask & IMAGE_COLOR_PIXMAP_MASK)
- type = IMAGE_COLOR_PIXMAP;
- else if (dest_mask & IMAGE_CURSOR_MASK)
- type = IMAGE_CURSOR;
- else
- {
- if (!no_error)
- signal_simple_error ("No compatible image-instance types given",
- instantiator);
- return 0;
- }
-
- x_initialize_pixmap_image_instance (ii);
- IMAGE_INSTANCE_PIXMAP_WIDTH (ii) = width;
- IMAGE_INSTANCE_PIXMAP_HEIGHT (ii) = height;
- IMAGE_INSTANCE_TYPE (ii) = type;
- IMAGE_INSTANCE_PIXMAP_FILENAME (ii) =
- find_keyword_in_vector (instantiator, Q_file);
- IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii) =
- find_keyword_in_vector (instantiator, Q_hotspot_x);
- IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii) =
- find_keyword_in_vector (instantiator, Q_hotspot_y);
-
- switch (type)
- {
- case IMAGE_MONO_PIXMAP:
- {
- IMAGE_INSTANCE_X_PIXMAP (ii) =
- XCreatePixmapFromBitmapData (DisplayOfScreen (scr),
- RootWindowOfScreen (scr),
- (char *) bits, width, height,
- 1, 0, 1);
- }
- break;
-
- case IMAGE_COLOR_PIXMAP:
- {
- Dimension d = DefaultDepthOfScreen (scr);
- unsigned long fg = BlackPixelOfScreen (scr);
- unsigned long bg = WhitePixelOfScreen (scr);
- XColor color;
- Colormap cmap = DefaultColormapOfScreen (scr);
-
- if (!NILP (foreground))
- foreground = Fmake_color_instance (foreground, device,
- no_error ? Qt : Qnil);
-
- /* Duplicate the pixel values so that we still have a lock on them if
- the pixels we were passed are later freed. */
- if (!NILP (foreground))
- {
- color = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (foreground));
- if (! XAllocColor (dpy, cmap, &color))
- abort ();
- fg = color.pixel;
- pixels_to_free[free_count++] = fg;
- }
-
- if (!NILP (background))
- background = Fmake_color_instance (background, device,
- no_error ? Qt : Qnil);
-
- /* Duplicate the pixel values so that we still have a lock on them if
- the pixels we were passed are later freed. */
- if (!NILP (background))
- {
- color = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (background));
- if (! XAllocColor (dpy, cmap, &color))
- abort ();
- bg = color.pixel;
- pixels_to_free[free_count++] = bg;
- }
-
- IMAGE_INSTANCE_X_PIXMAP (ii) =
- XCreatePixmapFromBitmapData (DisplayOfScreen (scr),
- RootWindowOfScreen (scr),
- (char *) bits, width, height,
- fg, bg, d);
- IMAGE_INSTANCE_PIXMAP_DEPTH (ii) = d;
- }
- break;
-
- case IMAGE_CURSOR:
- {
- XColor fg_color, bg_color;
- Pixmap source =
- XCreatePixmapFromBitmapData (DisplayOfScreen (scr),
- RootWindowOfScreen (scr),
- (char *) bits, width, height,
- 1, 0, 1);
-
- if (!NILP (foreground))
- foreground = Fmake_color_instance (foreground, device,
- no_error ? Qt : Qnil);
- if (!NILP (foreground))
- fg_color = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (foreground));
- else
- {
- fg_color.pixel = 0;
- fg_color.red = fg_color.green = fg_color.blue = 0;
- }
-
- if (!NILP (background))
- background = Fmake_color_instance (background, device,
- no_error ? Qt : Qnil);
- if (!NILP (background))
- bg_color = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (background));
- else
- {
- bg_color.pixel = 0;
- bg_color.red = bg_color.green = bg_color.blue = ~0;
- }
-
- IMAGE_INSTANCE_X_CURSOR (ii) =
- XCreatePixmapCursor
- (dpy, source, mask, &fg_color, &bg_color,
- !NILP (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii)) ?
- XINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii)) : 0,
- !NILP (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii)) ?
- XINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii)) : 0);
- }
- break;
-
- default:
- abort ();
- }
-
- if (free_count)
- {
- IMAGE_INSTANCE_X_NPIXELS (ii) = free_count;
- IMAGE_INSTANCE_X_PIXELS (ii) =
- xmalloc (free_count * sizeof (unsigned long));
- memcpy (IMAGE_INSTANCE_X_PIXELS (ii), pixels_to_free,
- free_count * sizeof (unsigned long));
- }
-
- return 1;
- }
-
- /* Instantiate method for XBM's. */
-
- static int
- xbm_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
- int dest_mask, int no_error)
- {
- Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
- Lisp_Object mask_data = find_keyword_in_vector (instantiator, Q_mask_data);
- struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
- Pixmap mask = 0;
-
- assert (!NILP (data));
-
- if (!NILP (mask_data))
- mask =
- pixmap_from_xbm_inline (IMAGE_INSTANCE_DEVICE (ii),
- XINT (XCAR (mask_data)),
- XINT (XCAR (XCDR (mask_data))),
- (char *) string_data
- (XSTRING (XCAR (XCDR (XCDR (mask_data))))));
-
- return (init_image_instance_from_xbm_inline
- (ii, XINT (XCAR (data)), XINT (XCAR (XCDR (data))),
- string_data (XSTRING (XCAR (XCDR (XCDR (data))))),
- instantiator, dest_mask, mask,
- find_keyword_in_vector (instantiator, Q_mask_file),
- no_error));
- }
-
-
- #ifdef HAVE_JPEG
-
- /**********************************************************************
- * JPEG *
- **********************************************************************/
-
- static int
- jpeg_validate (Lisp_Object instantiator, int no_error)
- {
- return file_or_data_must_be_present (instantiator, no_error);
- }
-
- static Lisp_Object
- jpeg_to_lisp_data (Lisp_Object name, int no_error, int ok_if_data_invalid)
- {
- }
-
- static Lisp_Object jpeg_normalize (Lisp_Object inst, Lisp_Object device_type,
- int no_error)
- {
- return Qnil;
- }
-
- static int
- jpeg_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
- int dest_mask, int no_error)
- {
- return 0;
- }
-
- #endif /* HAVE_JPEG */
-
-
- #ifdef HAVE_GIF
-
- /**********************************************************************
- * GIF *
- **********************************************************************/
-
- static int
- gif_validate (Lisp_Object instantiator, int no_error)
- {
- return file_or_data_must_be_present (instantiator, no_error);
- }
-
- static Lisp_Object
- gif_to_lisp_data (Lisp_Object name, int no_error, int ok_if_data_invalid)
- {
- }
-
- static Lisp_Object
- gif_normalize (Lisp_Object inst, Lisp_Object device_type,
- int no_error)
- {
- return Qnil;
- }
-
- static int
- gif_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
- int dest_mask, int no_error)
- {
- return 0;
- }
-
- #endif /* HAVE_GIF */
-
-
- #ifdef HAVE_PNG
-
- /**********************************************************************
- * PNG *
- **********************************************************************/
- static int
- png_validate (Lisp_Object instantiator, int no_error)
- {
- return file_or_data_must_be_present (instantiator, no_error);
- }
-
- static Lisp_Object
- png_to_lisp_data (Lisp_Object name, int no_error, int ok_if_data_invalid)
- {
- }
-
- static Lisp_Object
- png_normalize (Lisp_Object inst, Lisp_Object device_type,
- int no_error)
- {
- return Qnil;
- }
-
- static int
- png_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
- int dest_mask, int no_error)
- {
- return 0;
- }
-
- #endif /* HAVE_PNG */
-
-
- #ifdef HAVE_XPM
-
- /**********************************************************************
- * XPM *
- **********************************************************************/
-
- static int
- valid_xpm_color_symbols_p (Lisp_Object data, int no_error)
- {
- Lisp_Object rest;
-
- for (rest = data; !NILP (rest); rest = XCDR (rest))
- {
- if (!CONSP (rest) ||
- !CONSP (XCAR (rest)) ||
- !STRINGP (XCAR (XCAR (rest))) ||
- (!STRINGP (XCDR (XCAR (rest))) &&
- !COLOR_SPECIFIERP (XCDR (XCAR (rest)))))
- {
- if (!no_error)
- signal_simple_error ("Invalid color symbol alist",
- data);
- return 0;
- }
- }
-
- return 1;
- }
-
- static int
- xpm_validate (Lisp_Object instantiator, int no_error)
- {
- return file_or_data_must_be_present (instantiator, no_error);
- }
-
- static Lisp_Object
- pixmap_to_lisp_data (Lisp_Object name, int no_error, int ok_if_data_invalid)
- {
- char **data;
- int result;
-
- result = XpmReadFileToData ((char *) string_data (XSTRING (name)), &data);
-
- if (result == XpmSuccess)
- {
- Lisp_Object retval = Qnil;
- Lisp_Object old_inhibit_quit = Vinhibit_quit;
- struct buffer *old_buffer = current_buffer;
- Lisp_Object temp_buffer =
- Fget_buffer_create (build_string (" *pixmap conversion*"));
- int elt;
- int height, width, ncolors;
- struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
-
- GCPRO4 (name, retval, old_inhibit_quit, temp_buffer);
-
- Vinhibit_quit = Qt;
- set_buffer_internal (XBUFFER (temp_buffer));
- Ferase_buffer (Fcurrent_buffer ());
-
- buffer_insert_c_string (current_buffer, "/* XPM */\r");
- buffer_insert_c_string (current_buffer, "static char *pixmap[] = {\r");
-
- sscanf (data[0], "%d %d %d", &height, &width, &ncolors);
- for (elt = 0; elt <= width + ncolors; elt++)
- {
- buffer_insert_c_string (current_buffer, "\"");
- buffer_insert_c_string (current_buffer, data[elt]);
-
- if (elt < width + ncolors)
- buffer_insert_c_string (current_buffer, "\",\r");
- else
- buffer_insert_c_string (current_buffer, "\"};\r");
- }
-
- retval = Fbuffer_substring (Qnil, Qnil, Fcurrent_buffer ());
- XpmFree (data);
-
- set_buffer_internal (old_buffer);
- Vinhibit_quit = old_inhibit_quit;
-
- RETURN_UNGCPRO (retval);
- }
-
- switch (result)
- {
- case XpmFileInvalid:
- {
- if (ok_if_data_invalid)
- return Qt;
- if (!no_error)
- signal_simple_error ("invalid XPM data in file", name);
- break;
- }
- case XpmNoMemory:
- {
- if (!no_error)
- signal_double_file_error ("Reading pixmap file",
- "out of memory", name);
- break;
- }
- case XpmOpenFailed:
- {
- /* should never happen? */
- if (!no_error)
- signal_double_file_error ("Opening pixmap file",
- "no such file or directory", name);
- break;
- }
- default:
- {
- if (!no_error)
- signal_double_file_error_2 ("Parsing pixmap file",
- "unknown error code",
- make_number (result), name);
- break;
- }
- }
-
- return Qnil;
- }
-
- Lisp_Object Vxpm_color_symbols;
-
- static Lisp_Object
- evaluate_xpm_color_symbols (int no_error)
- {
- Lisp_Object rest, results = Qnil;
- struct gcpro gcpro1, gcpro2;
-
- GCPRO2 (rest, results);
- for (rest = Vxpm_color_symbols; !NILP (rest); rest = XCDR (rest))
- {
- Lisp_Object name, value, cons;
-
- if (!CONSP (rest))
- {
- if (!no_error)
- CHECK_CONS (rest, 0);
- UNGCPRO;
- return Qnil;
- }
- cons = XCAR (rest);
- if (!CONSP (cons))
- {
- if (!no_error)
- CHECK_CONS (cons, 0);
- UNGCPRO;
- return Qnil;
- }
- name = XCAR (cons);
- if (!STRINGP (name))
- {
- if (!no_error)
- CHECK_STRING (name, 0);
- UNGCPRO;
- return Qnil;
- }
- value = XCDR (cons);
- if (!CONSP (value))
- {
- if (!no_error)
- CHECK_CONS (value, 0);
- UNGCPRO;
- return Qnil;
- }
- value = XCAR (value);
- value = Feval (value);
- if (NILP (value))
- continue;
- if (!STRINGP (value) && !COLOR_SPECIFIERP (value))
- {
- if (!no_error)
- signal_simple_error
- ("Result from xpm-color-symbols eval must be nil, string, or color",
- value);
- UNGCPRO;
- return Qnil;
- }
- results = Fcons (Fcons (name, value), results);
- }
- UNGCPRO; /* no more evaluation */
- return results;
- }
-
- static Lisp_Object
- xpm_normalize (Lisp_Object inst, Lisp_Object device_type,
- int no_error)
- {
- Lisp_Object file = Qnil;
- Lisp_Object color_symbols;
- struct gcpro gcpro1, gcpro2;
- Lisp_Object alist = Qnil;
-
- GCPRO2 (file, alist);
-
- /* Now, convert any file data into inline data. At the end of this,
- `data' will contain the inline data (if any) or Qnil, and
- `file' will contain the name this data was derived from (if
- known) or Qnil.
-
- Note that if we cannot generate any regular inline data, we
- skip out. */
-
- file = potential_pixmap_file_instantiator (inst, Q_file, Q_data);
-
- if (EQ (file, Qt)) /* failure locating filename */
- {
- if (!no_error)
- signal_double_file_error ("Opening pixmap file",
- "no such file or directory",
- file);
- RETURN_UNGCPRO (Qnil);
- }
-
- color_symbols = find_keyword_in_vector_or_given (inst, Q_color_symbols,
- Qunbound);
-
- if (NILP (file) && !UNBOUNDP (color_symbols))
- /* no conversion necessary */
- RETURN_UNGCPRO (inst);
-
- alist = tagged_vector_to_alist (inst);
-
- if (!NILP (file))
- {
- Lisp_Object data = pixmap_to_lisp_data (file, no_error, 0);
- if (NILP (data)) /* conversion failure; error should
- already be signalled. */
- RETURN_UNGCPRO (Qnil);
- alist = remassq_no_quit (Q_file, alist);
- /* there can't be a :data at this point. */
- alist = Fcons (Fcons (Q_file, file),
- Fcons (Fcons (Q_data, data), alist));
- }
-
- if (UNBOUNDP (color_symbols))
- {
- color_symbols = evaluate_xpm_color_symbols (no_error);
- alist = Fcons (Fcons (Q_color_symbols, color_symbols),
- alist);
- }
-
- {
- Lisp_Object result = alist_to_tagged_vector (Qxpm, alist);
- free_alist (alist);
- RETURN_UNGCPRO (result);
- }
- }
-
- /* xpm 3.2g and better has XpmCreatePixmapFromBuffer()...
- There was no version number in xpm.h before 3.3, but this should do.
- */
- #if (XpmVersion >= 3) || defined(XpmExactColors)
- # define XPM_DOES_BUFFERS
- #endif
-
- #ifndef XPM_DOES_BUFFERS
- Your version of XPM is too old. You cannot compile with it.
- Upgrade to version 3.2g or better or compile with --with-xpm=no.
- #endif /* !XPM_DOES_BUFFERS */
-
- static XpmColorSymbol *
- extract_xpm_color_names (XpmAttributes *xpmattrs, Lisp_Object device,
- Lisp_Object color_symbol_alist, int no_error)
- {
- /* This function can GC */
- Screen *xs = LISP_DEVICE_TO_X_SCREEN (device);
- Display *dpy = DisplayOfScreen (xs);
- Colormap cmap = DefaultColormapOfScreen (xs);
- XColor color;
- Lisp_Object rest;
- Lisp_Object results = Qnil;
- int i;
- XpmColorSymbol *symbols;
- struct gcpro gcpro1, gcpro2;
-
- GCPRO2 (results, device);
-
- /* We built up results to be (("name" . #<color>) ...) so that if an
- error happens we don't lose any malloc()ed data, or more importantly,
- leave any pixels allocated in the server. */
- i = 0;
- LIST_LOOP (rest, color_symbol_alist)
- {
- Lisp_Object cons = XCAR (rest);
- Lisp_Object name = XCAR (cons);
- Lisp_Object value = XCDR (cons);
- if (NILP (value))
- continue;
- if (STRINGP (value))
- value = Fmake_color_instance (value, device, no_error ? Qt : Qnil);
- else
- {
- assert (COLOR_SPECIFIERP (value));
- value = Fspecifier_instance (value, device, Qnil, Qnil);
- }
- if (NILP (value))
- continue;
- results = Fcons (Fcons (name, value), results);
- i++;
- }
- UNGCPRO; /* no more evaluation */
-
- if (i == 0) return 0;
-
- symbols = (XpmColorSymbol *) xmalloc (i * sizeof (XpmColorSymbol));
- xpmattrs->valuemask |= XpmColorSymbols;
- xpmattrs->colorsymbols = symbols;
- xpmattrs->numsymbols = i;
-
- while (--i >= 0)
- {
- Lisp_Object cons = XCAR (results);
- color = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (XCDR (cons)));
- /* Duplicate the pixel value so that we still have a lock on it if
- the pixel we were passed is later freed. */
- if (! XAllocColor (dpy, cmap, &color))
- abort (); /* it must be allocable since we're just duplicating it */
-
- symbols [i].name = (char *) string_data (XSTRING (XCAR (cons)));
- symbols [i].pixel = color.pixel;
- symbols [i].value = 0;
- results = XCDR (results);
- free_cons (XCONS (cons));
- }
- return symbols;
- }
-
- static void
- xpm_free (XpmAttributes *xpmattrs)
- {
- /* Could conceivably lose if XpmXXX returned an error without first
- initializing this structure, if we didn't know that initializing it
- to all zeros was ok (and also that it's ok to call XpmFreeAttributes()
- multiple times, since it zeros slots as it frees them...) */
- XpmFreeAttributes (xpmattrs);
- }
-
- static int
- xpm_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
- int dest_mask, int no_error)
- {
- /* This function can GC */
- struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
- Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
- int force_mono;
- Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
- Screen *xs = LISP_DEVICE_TO_X_SCREEN (device);
- Pixmap pixmap;
- Pixmap mask = 0;
- XpmAttributes xpmattrs;
- int result;
- XpmColorSymbol *color_symbols;
- Lisp_Object color_symbol_alist = find_keyword_in_vector (instantiator,
- Q_color_symbols);
-
- if (dest_mask & IMAGE_COLOR_PIXMAP_MASK)
- force_mono = 0;
- else if (dest_mask & IMAGE_MONO_PIXMAP_MASK)
- force_mono = 1;
- else
- {
- if (!no_error)
- signal_simple_error ("No compatible image-instance types given",
- instantiator);
- return 0;
- }
-
- x_initialize_pixmap_image_instance (ii);
- if (force_mono)
- IMAGE_INSTANCE_TYPE (ii) = IMAGE_MONO_PIXMAP;
- else
- IMAGE_INSTANCE_TYPE (ii) = IMAGE_COLOR_PIXMAP;
-
- assert (!NILP (data));
-
- retry:
-
- memset (&xpmattrs, 0, sizeof (xpmattrs)); /* want XpmInitAttributes() */
- xpmattrs.valuemask = XpmReturnPixels;
- if (force_mono)
- {
- /* Without this, we get a 1-bit version of the color image, which
- isn't quite right. With this, we get the mono image, which might
- be very different looking. */
- xpmattrs.valuemask |= XpmColorKey;
- xpmattrs.color_key = XPM_MONO;
- xpmattrs.depth = 1;
- xpmattrs.valuemask |= XpmDepth;
- }
- else
- {
- xpmattrs.closeness = 65535;
- xpmattrs.valuemask |= XpmCloseness;
- }
-
- color_symbols = extract_xpm_color_names (&xpmattrs, device,
- color_symbol_alist,
- no_error);
-
- result = XpmCreatePixmapFromBuffer (DisplayOfScreen (xs),
- RootWindowOfScreen (xs),
- (char *)
- string_data (XSTRING (data)),
- &pixmap, &mask, &xpmattrs);
-
- if (color_symbols)
- {
- xfree (color_symbols);
- xpmattrs.colorsymbols = 0; /* in case XpmFreeAttr is too smart... */
- xpmattrs.numsymbols = 0;
- }
-
- switch (result)
- {
- case XpmSuccess:
- break;
- case XpmFileInvalid:
- {
- xpm_free (&xpmattrs);
- if (!no_error)
- signal_simple_error ("invalid XPM data", data);
- return 0;
- }
- case XpmColorFailed:
- case XpmColorError:
- {
- xpm_free (&xpmattrs);
- if (force_mono)
- {
- if (!no_error)
- /* second time; blow out. */
- signal_double_file_error ("Reading pixmap data",
- "color allocation failed",
- data);
- return 0;
- }
- else
- {
- if (! (dest_mask & IMAGE_MONO_PIXMAP_MASK))
- {
- if (!no_error)
- /* second time; blow out. */
- signal_double_file_error ("Reading pixmap data",
- "color allocation failed",
- data);
- return 0;
- }
- force_mono = 1;
- IMAGE_INSTANCE_TYPE (ii) = IMAGE_MONO_PIXMAP;
- goto retry;
- }
- }
- case XpmNoMemory:
- {
- xpm_free (&xpmattrs);
- if (!no_error)
- signal_double_file_error ("Parsing pixmap data",
- "out of memory", data);
- return 0;
- }
- default:
- {
- xpm_free (&xpmattrs);
- if (!no_error)
- signal_double_file_error_2 ("Parsing pixmap data",
- "unknown error code",
- make_number (result), data);
- else
- return 0;
- }
- }
- {
- /* XpmReadFileToPixmap() doesn't return the depth (bogus!) so we need to
- get it ourself. (No, xpmattrs.depth is not it; that's an input slot,
- not output.) We could just assume that it has the same depth as the
- root window, but some devices allow more than one depth, so that isn't
- necessarily correct (I guess?) */
- Window root;
- int x, y;
- unsigned int w2, h2, bw;
-
- unsigned int w = xpmattrs.width;
- unsigned int h = xpmattrs.height;
- unsigned int d;
- int xhot = ((xpmattrs.valuemask & XpmHotspot) ? xpmattrs.x_hotspot : -1);
- int yhot = ((xpmattrs.valuemask & XpmHotspot) ? xpmattrs.y_hotspot : -1);
- int npixels = xpmattrs.npixels;
- Pixel *pixels = 0;
-
- if (npixels != 0)
- {
- pixels = xmalloc (npixels * sizeof (Pixel));
- memcpy (pixels, xpmattrs.pixels, npixels * sizeof (Pixel));
- }
- else
- pixels = 0;
-
- xpm_free (&xpmattrs); /* after we've read pixels and hotspot */
-
- if (!XGetGeometry (DisplayOfScreen (xs), pixmap, &root, &x, &y,
- &w2, &h2, &bw, &d))
- abort ();
- if (w != w2 || h != h2)
- abort ();
-
- {
- IMAGE_INSTANCE_PIXMAP_FILENAME (ii) =
- find_keyword_in_vector (instantiator, Q_file);
- if (xhot >= 0)
- IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii) = make_number (xhot);
- if (yhot >= 0)
- IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii) = make_number (yhot);
- IMAGE_INSTANCE_X_PIXMAP (ii) = pixmap;
- IMAGE_INSTANCE_X_MASK (ii) = mask;
- IMAGE_INSTANCE_PIXMAP_WIDTH (ii) = w;
- IMAGE_INSTANCE_PIXMAP_HEIGHT (ii) = h;
- IMAGE_INSTANCE_PIXMAP_DEPTH (ii) = d;
- IMAGE_INSTANCE_X_PIXELS (ii) = pixels;
- IMAGE_INSTANCE_X_NPIXELS (ii) = npixels;
- }
- }
-
- return 1;
- }
-
- #endif /* HAVE_XPM */
-
-
- #ifdef HAVE_XFACE
-
- /**********************************************************************
- * X-Face *
- **********************************************************************/
-
- static int
- xface_validate (Lisp_Object instantiator, int no_error)
- {
- return file_or_data_must_be_present (instantiator, no_error);
- }
-
- static Lisp_Object
- xface_normalize (Lisp_Object inst, Lisp_Object device_type,
- int no_error)
- {
- Lisp_Object file = Qnil;
- struct gcpro gcpro1, gcpro2;
- Lisp_Object alist = Qnil;
-
- GCPRO2 (file, alist);
-
- /* Now, convert any file data into inline data for both the regular
- data and the mask data. At the end of this, `data' will contain
- the inline data (if any) or Qnil, and `file' will contain
- the name this data was derived from (if known) or Qnil.
- Likewise for `mask_file' and `mask_data'.
-
- Note that if we cannot generate any regular inline data, we
- skip out. */
-
- file = potential_pixmap_file_instantiator (inst, Q_file, Q_data);
-
- if (EQ (file, Qt)) /* failure locating filename */
- {
- if (!no_error)
- signal_double_file_error ("Opening bitmap file",
- "no such file or directory",
- file);
- RETURN_UNGCPRO (Qnil);
- }
-
- if (NILP (file)) /* no conversion necessary */
- RETURN_UNGCPRO (inst);
-
- alist = tagged_vector_to_alist (inst);
-
- {
- Lisp_Object data = make_string_from_file (file);
- alist = remassq_no_quit (Q_file, alist);
- /* there can't be a :data at this point. */
- alist = Fcons (Fcons (Q_file, file),
- Fcons (Fcons (Q_data, data), alist));
- }
-
- {
- Lisp_Object result = alist_to_tagged_vector (Qxface, alist);
- free_alist (alist);
- RETURN_UNGCPRO (result);
- }
- }
-
- /* We have to define SYSV32 so that compface.h includes string.h
- instead of strings.h. */
- #define SYSV32
- #include <compface.h>
- jmp_buf comp_env;
- #undef SYSV32
-
- static int
- xface_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
- int dest_mask, int no_error)
- {
- Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
- struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
- int i, status;
- char *p, *bits, *bp, *emsg = NULL, *dstring;
-
- assert (!NILP (data));
-
- dstring = (char *) string_data (XSTRING (data));
-
- if ((p = strchr (dstring, ':')))
- {
- dstring = p + 1;
- }
-
- if (!(status = setjmp (comp_env)))
- {
- UnCompAll (dstring);
- UnGenFace ();
- }
-
- switch (status)
- {
- case -2:
- emsg = "uncompface: internal error";
- break;
- case -1:
- emsg = "uncompface: insufficient or invalid data";
- break;
- case 1:
- emsg = "uncompface: excess data ignored";
- break;
- }
-
- if (emsg)
- {
- if (!no_error)
- signal_simple_error (emsg, data);
- return 0;
- }
-
- bp = bits = (char *) alloca (PIXELS / 8);
-
- /* the compface library exports char F[], which uses a single byte per
- pixel to represent a 48x48 bitmap. Yuck. */
- for (i = 0, p = F; i < (PIXELS / 8); ++i)
- {
- int n, b;
- /* reverse the bit order of each byte... */
- for (b = n = 0; b < 8; ++b)
- {
- n |= ((*p++) << b);
- }
- *bp++ = (char) n;
- }
-
- return init_image_instance_from_xbm_inline (ii, 48, 48,
- (unsigned char *) bits,
- instantiator, dest_mask,
- 0, Qnil, no_error);
- }
-
- #endif /* HAVE_XFACE */
-
-
- /**********************************************************************
- * Autodetect *
- **********************************************************************/
-
- static int
- autodetect_validate (Lisp_Object instantiator, int no_error)
- {
- return data_must_be_present (instantiator, no_error);
- }
-
- static Lisp_Object
- autodetect_normalize (Lisp_Object instantiator, Lisp_Object device_type,
- int no_error)
- {
- Lisp_Object file = find_keyword_in_vector (instantiator, Q_data);
- Lisp_Object filename = Qnil;
- Lisp_Object data = Qnil;
- struct gcpro gcpro1, gcpro2, gcpro3;
- Lisp_Object alist = Qnil;
-
- GCPRO3 (filename, data, alist);
-
- if (NILP (file)) /* no conversion necessary */
- RETURN_UNGCPRO (instantiator);
-
- alist = tagged_vector_to_alist (instantiator);
-
- filename = locate_pixmap_file (file);
- if (!NILP (filename))
- {
- int xhot, yhot;
- /* #### Apparently some versions of XpmReadFileToData which is
- called by pixmap_to_lisp_data don't return an error value
- if the given file is not a valid XPM file. Instead, they
- just seg fault. It is definitely caused by passing a
- bitmap. To try and avoid this we check for bitmaps first. */
-
- data = bitmap_to_lisp_data (filename, &xhot, &yhot, no_error, 1);
- if (NILP (data))
- /* error in conversion, other than invalid data */
- RETURN_UNGCPRO (Qnil);
-
- if (!EQ (data, Qt))
- {
- alist = remassq_no_quit (Q_data, alist);
- alist = Fcons (Fcons (Q_file, filename),
- Fcons (Fcons (Q_data, data), alist));
- if (xhot != -1)
- alist = Fcons (Fcons (Q_hotspot_x, make_number (xhot)),
- alist);
- if (yhot != -1)
- alist = Fcons (Fcons (Q_hotspot_y, make_number (yhot)),
- alist);
-
- {
- Lisp_Object result = alist_to_tagged_vector (Qxbm, alist);
- free_alist (alist);
- RETURN_UNGCPRO (result);
- }
- }
-
- #ifdef HAVE_XPM
- data = pixmap_to_lisp_data (filename, no_error, 1);
- if (NILP (data)) /* conversion failure; error should
- already be signalled. */
- RETURN_UNGCPRO (Qnil);
-
- if (!EQ (data, Qt))
- {
- alist = remassq_no_quit (Q_data, alist);
- alist = Fcons (Fcons (Q_file, filename),
- Fcons (Fcons (Q_data, data), alist));
- alist = Fcons (Fcons (Q_color_symbols,
- evaluate_xpm_color_symbols (no_error)),
- alist);
- {
- Lisp_Object result = alist_to_tagged_vector (Qxpm, alist);
- free_alist (alist);
- RETURN_UNGCPRO (result);
- }
- }
- #endif
- }
-
- alist = remassq_no_quit (Q_data, alist);
- alist = Fcons (Fcons (Q_data, file), alist);
-
- {
- Lisp_Object result = alist_to_tagged_vector (Qstring, alist);
- free_alist (alist);
- RETURN_UNGCPRO (result);
- }
- }
-
- static int
- autodetect_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
- int dest_mask, int no_error)
- {
- abort (); /* Should never get here. Anything that was `autodetect'
- should have been converted to something else by the
- normalization code. */
- return 0;
- }
-
-
- /**********************************************************************
- * Misc image *
- **********************************************************************/
-
- /* #### This function could fuck with pixmap caches. Need to rethink. */
-
- DEFUN ("colorize-image-instance", Fcolorize_image_instance,
- Scolorize_image_instance, 3, 3, 0,
- "Make the image instance be displayed in the given colors.\n\
- Image instances come in two varieties: bitmaps, which are 1 bit deep which\n\
- are rendered in the prevailing foreground and background colors; and\n\
- pixmaps, which are of arbitrary depth (including 1) and which have the\n\
- colors explicitly specified. This function converts a bitmap to a pixmap.\n\
- If the image instance was a pixmap already, nothing is done (and nil is\n\
- returned). Otherwise t is returned.")
- (image_instance, foreground, background)
- Lisp_Object image_instance, foreground, background;
- {
- struct Lisp_Image_Instance *p;
-
- CHECK_IMAGE_INSTANCE (image_instance, 0);
- CHECK_COLOR_INSTANCE (foreground, 0);
- CHECK_COLOR_INSTANCE (background, 0);
- p = XIMAGE_INSTANCE (image_instance);
- if (IMAGE_INSTANCE_PIXMAP_DEPTH (p) > 0)
- return Qnil;
- {
- Display *dpy = DEVICE_X_DISPLAY (XDEVICE (IMAGE_INSTANCE_DEVICE (p)));
- Screen *scr = DefaultScreenOfDisplay (dpy);
- Dimension d = DefaultDepthOfScreen (scr);
- Colormap cmap = DefaultColormapOfScreen (scr);
- Pixmap new = XCreatePixmap (dpy, RootWindowOfScreen (scr),
- IMAGE_INSTANCE_PIXMAP_WIDTH (p),
- IMAGE_INSTANCE_PIXMAP_HEIGHT (p), d);
- XColor color;
- XGCValues gcv;
- GC gc;
- /* Duplicate the pixel values so that we still have a lock on them if
- the pixels we were passed are later freed. */
- color = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (foreground));
- if (! XAllocColor (dpy, cmap, &color)) abort ();
- gcv.foreground = color.pixel;
- color = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (background));
- if (! XAllocColor (dpy, cmap, &color)) abort ();
- gcv.background = color.pixel;
- gc = XCreateGC (dpy, new, GCBackground|GCForeground, &gcv);
- XCopyPlane (dpy, IMAGE_INSTANCE_X_PIXMAP (p), new, gc, 0, 0,
- IMAGE_INSTANCE_PIXMAP_WIDTH (p), IMAGE_INSTANCE_PIXMAP_HEIGHT (p),
- 0, 0, 1);
- XFreeGC (dpy, gc);
- XFreePixmap (dpy, IMAGE_INSTANCE_X_PIXMAP (p));
- IMAGE_INSTANCE_X_PIXMAP (p) = new;
- IMAGE_INSTANCE_PIXMAP_DEPTH (p) = d;
- }
- return Qt;
- }
-
-
- /************************************************************************/
- /* cursors */
- /************************************************************************/
-
- /* #### this shit needs overhauling and specifierifying */
-
- Lisp_Object Qcursorp;
- static Lisp_Object mark_cursor (Lisp_Object, void (*) (Lisp_Object));
- static void print_cursor (Lisp_Object, Lisp_Object, int);
- static void finalize_cursor (void *, int);
- static int cursor_equal (Lisp_Object, Lisp_Object, int depth);
- static unsigned long cursor_hash (Lisp_Object obj, int depth);
- DEFINE_LRECORD_IMPLEMENTATION ("cursor", cursor,
- mark_cursor, print_cursor, finalize_cursor,
- cursor_equal, cursor_hash, struct Lisp_Cursor);
-
- static Lisp_Object
- mark_cursor (Lisp_Object obj, void (*markobj) (Lisp_Object))
- {
- struct Lisp_Cursor *c = XCURSOR (obj);
- ((markobj) (c->fg));
- ((markobj) (c->bg));
- ((markobj) (c->name));
- return c->device;
- }
-
- static void
- print_cursor (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
- {
- char buf[200];
- struct Lisp_Cursor *c = XCURSOR (obj);
- if (print_readably)
- error ("printing unreadable object #<cursor 0x%x>",
- c->header.uid);
-
- write_c_string ("#<cursor ", printcharfun);
- print_internal (c->name, printcharfun, 1);
- if (!NILP (c->fg))
- {
- write_c_string (" (", printcharfun);
- print_internal (XCOLOR_INSTANCE (c->fg)->name, printcharfun, 0);
- write_c_string ("/", printcharfun);
- print_internal (XCOLOR_INSTANCE (c->bg)->name, printcharfun, 0);
- write_c_string (")", printcharfun);
- }
- sprintf (buf, " 0x%x>", c->header.uid);
- /* #### should print the device */
- write_c_string (buf, printcharfun);
- }
-
- static void
- finalize_cursor (void *header, int for_disksave)
- {
- struct Lisp_Cursor *c = (struct Lisp_Cursor *) header;
- if (for_disksave) finalose (c);
- if (c->cursor)
- {
- XFreeCursor (DEVICE_X_DISPLAY (XDEVICE (c->device)), c->cursor);
- c->cursor = 0;
- }
- }
-
- /* Cursors are equal if their names are equal. */
- static int
- cursor_equal (Lisp_Object o1, Lisp_Object o2, int depth)
- {
- return (internal_equal (XCURSOR (o1)->name, XCURSOR (o2)->name, depth + 1));
- }
-
- static unsigned long
- cursor_hash (Lisp_Object obj, int depth)
- {
- return internal_hash (XCURSOR (obj)->name, depth + 1);
- }
-
- /* XmuCvtStringToCursor is bogus in the following ways:
-
- - When it can't convert the given string to a real cursor, it will
- sometimes return a "success" value, after triggering a BadPixmap
- error. It then gives you a cursor that will itself generate BadCursor
- errors. So we install this error handler to catch/notice the X error
- and take that as meaning "couldn't convert."
-
- - When you tell it to find a cursor file that doesn't exist, it prints
- an error message on stderr. You can't make it not do that.
-
- - Also, using Xmu means we can't properly hack Lisp_Image_Instance
- objects, or XPM files, or $XBMLANGPATH.
- */
-
- /* Duplicate the behavior of XmuCvtStringToCursor() to bypass its bogusness. */
-
- static int XLoadFont_got_error;
- static int XLoadFont_error_handler (Display *dpy, XErrorEvent *xerror)
- {
- XLoadFont_got_error = 1;
- return 0;
- }
-
- static Font
- safe_XLoadFont (Display *dpy, char *name)
- {
- Font font;
- int (*old_handler) ();
- XLoadFont_got_error = 0;
- XSync (dpy, 0);
- old_handler = XSetErrorHandler (XLoadFont_error_handler);
- font = XLoadFont (dpy, name);
- XSync (dpy, 0);
- XSetErrorHandler (old_handler);
- if (XLoadFont_got_error) return 0;
- return font;
- }
-
-
- static Cursor
- make_cursor_1 (Lisp_Object device, Lisp_Object name)
- {
- /* This function can GC */
- Screen *xs = LISP_DEVICE_TO_X_SCREEN (device);
- Display *dpy = DisplayOfScreen (xs);
- XColor fg, bg;
- Cursor cursor;
- int i;
-
- fg.pixel = bg.pixel = 0;
- fg.red = fg.green = fg.blue = 0;
- bg.red = bg.green = bg.blue = ~0;
-
- if (STRINGP (name) &&
- !strncmp ("FONT ", (char *) string_data (XSTRING (name)), 5))
- {
- Font source, mask;
- char source_name [MAXPATHLEN], mask_name [MAXPATHLEN], dummy;
- int source_char, mask_char;
- int count = sscanf ((char *) string_data (XSTRING (name)),
- "FONT %s %d %s %d %c",
- source_name, &source_char,
- mask_name, &mask_char, &dummy);
- /* Allow "%s %d %d" as well... */
- if (count == 3 && (1 == sscanf (mask_name, "%d %c", &mask_char, &dummy)))
- count = 4, mask_name[0] = 0;
-
- if (count != 2 && count != 4)
- signal_simple_error ("invalid cursor specification", name);
- source = safe_XLoadFont (dpy, source_name);
- if (! source)
- signal_simple_error_2 ("couldn't load font",
- build_string (source_name),
- name);
- if (count == 2)
- mask = 0;
- else if (! mask_name[0])
- mask = source;
- else
- {
- mask = safe_XLoadFont (dpy, mask_name);
- if (! mask) /* continuable */
- Fsignal (Qerror, list3 (build_string ("couldn't load font"),
- build_string (mask_name), name));
- }
- if (! mask) mask_char = 0;
-
- /* #### call XQueryTextExtents() and check_pointer_sizes() here. */
-
- cursor = XCreateGlyphCursor (dpy, source, mask, source_char, mask_char,
- &fg, &bg);
- XUnloadFont (dpy, source);
- if (mask && mask != source) XUnloadFont (dpy, mask);
- }
-
- else if (STRINGP (name) &&
- (i = XmuCursorNameToIndex (string_ext_data (XSTRING (name)))) != -1)
- {
- cursor = XCreateFontCursor (dpy, i);
- }
-
- else
- {
- struct gcpro gcpro1, gcpro2, gcpro3;
- Lisp_Object lsource = Qnil;
- Lisp_Object lmask = Qnil;
- Lisp_Object mask_file = Qnil;
- Pixmap source, mask;
-
- GCPRO3 (lsource, lmask, mask_file);
-
- if (IMAGE_INSTANCEP (name))
- lsource = name;
- else if (GLYPHP (name))
- lsource = glyph_image_instance (name, device, 0);
- else
- /* #### We may not want this to error later on. */
- lsource = Fmake_image_instance (name, device, Qmono_pixmap, Qnil);
-
- if (!IMAGE_INSTANCEP (lsource))
- signal_simple_error ("Could not obtain image instance", name);
-
- if (XIMAGE_INSTANCE_TYPE (lsource) != IMAGE_MONO_PIXMAP)
- signal_simple_error ("Invalid image-instance type", lsource);
- source = XIMAGE_INSTANCE_X_PIXMAP (lsource);
- mask = XIMAGE_INSTANCE_X_MASK (lsource);
-
- if (XIMAGE_INSTANCE_PIXMAP_DEPTH (lsource) > 1)
- signal_error (Qerror,
- list3 (build_string ("cursor image instances must be 1 plane"),
- name, lsource));
- if (!mask && STRINGP (name))
- {
- mask_file =
- locate_pixmap_file (concat2 (name, build_string ("Mask")));
- if (NILP (mask_file))
- mask_file =
- locate_pixmap_file (concat2 (name, build_string ("msk")));
- if (!NILP (mask_file))
- {
- /* #### We may not want this to error later on. */
- lmask = Fmake_image_instance (mask_file, device, Qmono_pixmap,
- Qnil);
- if (!IMAGE_INSTANCEP (lmask))
- signal_simple_error
- ("Could not obtain mask image instance", lmask);
- if (XIMAGE_INSTANCE_PIXMAP_DEPTH (lmask) != 0)
- signal_simple_error_2 ("mask must be 1 bit deep",
- mask_file, lmask);
- mask = XIMAGE_INSTANCE_X_PIXMAP (lmask);
- mask_file = Qnil;
- }
- }
-
- check_pointer_sizes (xs,
- XIMAGE_INSTANCE_PIXMAP_WIDTH (lsource),
- XIMAGE_INSTANCE_PIXMAP_HEIGHT (lsource),
- name, 0);
-
- /* If the loaded pixmap has colors allocated (meaning it came from an
- XPM file), then use those as the default colors for the cursor we
- create. Otherwise, default to black and white.
- */
- if (XIMAGE_INSTANCE_X_NPIXELS (lsource) >= 2)
- {
- int npixels = XIMAGE_INSTANCE_X_NPIXELS (lsource);
- unsigned long *pixels = XIMAGE_INSTANCE_X_PIXELS (lsource);
-
- /* With an XBM file, it's obvious which bit is foreground and which
- is background, or rather, it's implicit: in an XBM file, a 1 bit
- is foreground, and a 0 bit is background.
-
- XCreatePixmapCursor() assumes this property of the pixmap it is
- called with as well; the `foreground' color argument is used for
- the 1 bits.
-
- With an XPM file, it's tricker, since the elements of the pixmap
- don't represent FG and BG, but are actual pixel values. So we
- need to figure out which of those pixels is the foreground color
- and which is the background. We do it by comparing RGB and
- assuming that the darker color is the foreground. This works
- with the result of xbmtopbm|ppmtoxpm, at least.
-
- It might be nice if there was some way to tag the colors in the
- XPM file with whether they are the foreground - perhaps with
- logical color names somehow?
-
- Once we have decided which color is the foreground, we need to
- ensure that that color corresponds to a `1' bit in the Pixmap.
- The XPM library wrote into the (1-bit) pixmap with XPutPixel,
- which will ignore all but the least significant bit.
-
- This means that a 1 bit in the image corresponds to `fg' only if
- `fg.pixel' is odd.
-
- (This also means that the image will be all the same color if
- both `fg' and `bg' are odd or even, but we can safely assume
- that that won't happen if the XPM file is sensible I think.)
-
- The desired result is that the image use `1' to represent the
- foreground color, and `0' to represent the background color.
- So, we may need to invert the image to accomplish this; we invert
- if fg is odd. (Remember that WhitePixel and BlackPixel are not
- necessarily 1 and 0 respectively, though I think it might be safe
- to assume that one of them is always 1 and the other is always 0.
- We also pretty much need to assume that one is even and the other
- is odd.)
- */
-
- fg.pixel = pixels [0]; /* pick a pixel at random. */
- bg.pixel = fg.pixel;
- for (i = 1; i < npixels; i++) /* Look for an "other" pixel value. */
- {
- bg.pixel = pixels [i];
- if (fg.pixel != bg.pixel) break;
- }
-
- /* If (fg.pixel == bg.pixel) then probably something has gone wrong,
- but I don't think signalling an error would be appropriate. */
-
- XQueryColor (DisplayOfScreen(xs), DefaultColormapOfScreen(xs), &fg);
- XQueryColor (DisplayOfScreen(xs), DefaultColormapOfScreen(xs), &bg);
-
- /* If the foreground is lighter than the background, swap them.
- (This occurs semi-randomly, depending on the ordering of the
- color list in the XPM file.)
- */
- {
- unsigned short fg_total = ((fg.red / 3) + (fg.green / 3)
- + (fg.blue / 3));
- unsigned short bg_total = ((bg.red / 3) + (bg.green / 3)
- + (bg.blue / 3));
- if (fg_total > bg_total)
- {
- XColor swap;
- swap = fg;
- fg = bg;
- bg = swap;
- }
- }
-
- /* If the fg pixel corresponds to a `0' in the bitmap, invert it.
- (This occurs (only?) on servers with Black=0, White=1.)
- */
- if ((fg.pixel & 1) == 0)
- {
- XGCValues gcv;
- GC gc;
- gcv.function = GXxor;
- gcv.foreground = 1;
- gc = XCreateGC (dpy, source, (GCFunction | GCForeground), &gcv);
- XFillRectangle (dpy, source, gc, 0, 0,
- XIMAGE_INSTANCE_PIXMAP_WIDTH (lsource),
- XIMAGE_INSTANCE_PIXMAP_HEIGHT (lsource));
- XFreeGC (dpy, gc);
- }
- }
-
- cursor = XCreatePixmapCursor
- (dpy, source, mask, &fg, &bg,
- !NILP (XIMAGE_INSTANCE_PIXMAP_HOTSPOT_X (lsource)) ?
- XINT (XIMAGE_INSTANCE_PIXMAP_HOTSPOT_X (lsource)) : 0,
- !NILP (XIMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (lsource)) ?
- XINT (XIMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (lsource)) : 0);
- UNGCPRO; /* can now collect and free `lsource', `lmask', and Pixmaps. */
- }
- return cursor;
- }
-
- DEFUN ("make-cursor", Fmake_cursor, Smake_cursor, 1, 4, 0,
- "Creates a new `cursor' object of the specified name.\n\
- The optional second and third arguments are the foreground and background\n\
- colors. They may be color name strings or `pixel' objects.\n\
- The optional fourth argument is the device on which to allocate the cursor\n\
- (defaults to the selected device).\n\
- This allocates a new cursor in the X server, and signals an error if the\n\
- cursor is unknown or cannot be allocated.\n\
- \n\
- A cursor name can take many different forms. It can be:\n\
- - any of the standard cursor names from appendix B of the Xlib manual\n\
- (also known as the file <X11/cursorfont.h>) minus the XC_ prefix;\n\
- - the name of a font, and glyph index into it of the form\n\
- \"FONT fontname index [[mask-font] mask-index]\";\n\
- - the name of a bitmap or pixmap file;\n\
- - or an image instance object, as returned by `make-image-instance'.\n\
- \n\
- If it is an image instance or pixmap file, and that pixmap comes with a\n\
- mask, then that mask will be used. If it is an image instance, it must\n\
- have only one plane, since X cursors may only have two colors. If it is a\n\
- pixmap file, then the file will be read in monochrome.\n\
- \n\
- If it is a bitmap file, and if a bitmap file whose name is the name of the\n\
- cursor with \"msk\" or \"Mask\" appended exists, then that second bitmap\n\
- will be used as the mask. For example, a pair of files might be named\n\
- \"cursor.xbm\" and \"cursor.xbmmsk\".\n\
- \n\
- The returned object is a normal, first-class lisp object. The way you\n\
- `deallocate' the cursor is the way you deallocate any other lisp object:\n\
- you drop all pointers to it and allow it to be garbage collected. When\n\
- these objects are GCed, the underlying X data is deallocated as well.")
- (name, fg, bg, device)
- Lisp_Object name, fg, bg, device;
- {
- /* This function can GC */
- Screen *xs;
- Cursor cursor;
-
- XSETDEVICE (device, get_x_device (device));
- xs = LISP_DEVICE_TO_X_SCREEN (device);
-
- if ((NILP (fg)) != (NILP (bg)))
- error ("must specify both foreground and background, or neither.");
-
- if (STRINGP (fg))
- fg = Fmake_color_instance (fg, device, Qnil);
- else if (!NILP (fg) && !COLOR_INSTANCEP (fg))
- CHECK_STRING (fg, 0);
-
- if (STRINGP (bg))
- bg = Fmake_color_instance (bg, device, Qnil);
- else if (!NILP (bg) && !COLOR_INSTANCEP (bg))
- CHECK_STRING (bg, 0);
-
- cursor = make_cursor_1 (device, name);
-
- if (! cursor)
- signal_simple_error ("unknown cursor", name);
-
- /* Got the cursor, now color it in.
- (Either both are specified or neither.) */
- if (!NILP (fg))
- {
- XColor xbg, xfg;
-
- xbg = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (bg));
- xfg = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (fg));
-
- XRecolorCursor (DisplayOfScreen (xs), cursor,
- &xfg, &xbg);
- }
-
- /* Now make the lisp object. */
- {
- struct Lisp_Cursor *c = alloc_lcrecord (sizeof (struct Lisp_Cursor),
- lrecord_cursor);
- Lisp_Object val;
- c->device = device;
- c->name = name;
- c->cursor = cursor;
- c->fg = fg;
- c->bg = bg;
- XSETCURSOR (val, c);
- return val;
- }
- }
-
- DEFUN ("cursorp", Fcursorp, Scursorp, 1, 1, 0,
- "Return non-nil if OBJECT is a cursor.")
- (object)
- Lisp_Object object;
- {
- return (CURSORP (object) ? Qt : Qnil);
- }
-
- DEFUN ("cursor-name", Fcursor_name, Scursor_name, 1, 1, 0,
- "Return the name used to allocate the given cursor.")
- (cursor)
- Lisp_Object cursor;
- {
- CHECK_CURSOR (cursor, 0);
- return (XCURSOR (cursor)->name);
- }
-
- DEFUN ("cursor-foreground", Fcursor_foreground, Scursor_foreground, 1, 1, 0,
- "Return the foreground color of the given cursor, or nil if unspecified.")
- (cursor)
- Lisp_Object cursor;
- {
- CHECK_CURSOR (cursor, 0);
- return (XCURSOR (cursor)->fg);
- }
-
- DEFUN ("cursor-background", Fcursor_background, Scursor_background, 1, 1, 0,
- "Return the background color of the given cursor, or nil if unspecified.")
- (cursor)
- Lisp_Object cursor;
- {
- CHECK_CURSOR (cursor, 0);
- return (XCURSOR (cursor)->bg);
- }
-
-
- /************************************************************************/
- /* subwindows */
- /************************************************************************/
-
- Lisp_Object Qsubwindowp;
- static Lisp_Object mark_subwindow (Lisp_Object, void (*) (Lisp_Object));
- static void print_subwindow (Lisp_Object, Lisp_Object, int);
- static void finalize_subwindow (void *, int);
- static int subwindow_equal (Lisp_Object o1, Lisp_Object o2, int depth);
- static unsigned long subwindow_hash (Lisp_Object obj, int depth);
- DEFINE_LRECORD_IMPLEMENTATION ("subwindow", subwindow,
- mark_subwindow, print_subwindow,
- finalize_subwindow, subwindow_equal,
- subwindow_hash, struct Lisp_Subwindow);
-
- static Lisp_Object
- mark_subwindow (Lisp_Object obj, void (*markobj) (Lisp_Object))
- {
- struct Lisp_Subwindow *sw = XSUBWINDOW (obj);
- return sw->frame;
- }
-
- static void
- print_subwindow (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
- {
- char buf[100];
- struct Lisp_Subwindow *sw = XSUBWINDOW (obj);
- struct frame *frm = XFRAME (sw->frame);
-
- if (print_readably)
- error ("printing unreadable object #<subwindow 0x%x>",
- sw->header.uid);
-
- write_c_string ("#<subwindow", printcharfun);
- sprintf (buf, " %dx%d", sw->width, sw->height);
- write_c_string (buf, printcharfun);
-
- /* This is stolen from frame.c. Subwindows are strange in that they
- are specific to a particular frame so we want to print in their
- description what that frame is. */
-
- write_c_string (" on #<", printcharfun);
- if (!FRAME_LIVE_P (frm))
- write_c_string ("dead", printcharfun);
- else if (FRAME_IS_TTY (frm))
- write_c_string ("tty", printcharfun);
- else if (FRAME_IS_X (frm))
- write_c_string ("x", printcharfun);
- else
- write_c_string ("UNKNOWN", printcharfun);
- write_c_string ("-frame ", printcharfun);
- print_internal (frm->name, printcharfun, 1);
- sprintf (buf, " 0x%x>", frm->header.uid);
- write_c_string (buf, printcharfun);
-
- sprintf (buf, ") 0x%x>", sw->header.uid);
- write_c_string (buf, printcharfun);
- }
-
- static void
- finalize_subwindow (void *header, int for_disksave)
- {
- struct Lisp_Subwindow *sw = (struct Lisp_Subwindow *) header;
- if (for_disksave) finalose (sw);
- if (sw->subwindow)
- {
- XDestroyWindow (DisplayOfScreen (sw->xscreen), sw->subwindow);
- sw->subwindow = 0;
- }
- }
-
- /* subwindows are equal iff they have the same window XID */
- static int
- subwindow_equal (Lisp_Object o1, Lisp_Object o2, int depth)
- {
- return (XSUBWINDOW (o1)->subwindow == XSUBWINDOW (o2)->subwindow);
- }
-
- static unsigned long
- subwindow_hash (Lisp_Object obj, int depth)
- {
- return XSUBWINDOW (obj)->subwindow;
- }
-
- /* #### PROBLEM: The display routines assume that the glyph is only
- being displayed in one buffer. If it is in two different buffers
- which are both being displayed simultaneously you will lose big time.
- This can be dealt with in the new redisplay. */
-
- /* #### These are completely un-re-implemented in 19.13. Get it done
- for 19.14. */
-
- DEFUN ("make-subwindow", Fmake_subwindow, Smake_subwindow,
- 0, 3, 0,
- "Creates a new `x-window' object of size WIDTH x HEIGHT.\n\
- The default is a window of size 1x1, which is also the minimum allowed\n\
- window size. Subwindows are per-frame. A buffer being shown in two\n\
- different frames will only display a subwindow glyph in the frame in\n\
- which it was actually created. If two windows on the same frame are\n\
- displaying the buffer then the most recently used window will actually\n\
- display the window. If the frame is not specified, the selected frame\n\
- is used.")
- (width, height, frame)
- Lisp_Object width, height, frame;
- {
- Display *dpy;
- Screen *xs;
- Window pw;
- struct frame *f;
- unsigned int iw, ih;
- XSetWindowAttributes xswa;
- Mask valueMask = 0;
-
- error ("subwindows are not functional in 19.13; they will be in 19.14");
-
- f = get_x_frame (frame);
-
- xs = LISP_DEVICE_TO_X_SCREEN (FRAME_DEVICE (f));
- dpy = DisplayOfScreen (xs);
- pw = XtWindow (FRAME_X_TEXT_WIDGET (f));
-
- if (NILP (width))
- iw = 1;
- else
- {
- CHECK_INT (width, 0);
- iw = XINT (width);
- if (iw < 1) iw = 1;
- }
- if (NILP (height))
- ih = 1;
- else
- {
- CHECK_INT (height, 0);
- ih = XINT (height);
- if (ih < 1) ih = 1;
- }
-
- {
- struct Lisp_Subwindow *sw = alloc_lcrecord (sizeof (struct Lisp_Subwindow),
- lrecord_subwindow);
- Lisp_Object val;
- sw->frame = frame;
- sw->xscreen = xs;
- sw->parent_window = pw;
- sw->height = ih;
- sw->width = iw;
-
- xswa.backing_store = Always;
- valueMask |= CWBackingStore;
-
- xswa.colormap = DefaultColormapOfScreen (xs);
- valueMask |= CWColormap;
-
- sw->subwindow = XCreateWindow (dpy, pw, 0, 0, iw, ih, 0, CopyFromParent,
- InputOutput, CopyFromParent, valueMask,
- &xswa);
-
- XSETSUBWINDOW (val, sw);
- return val;
- }
- }
-
- /* #### Should this function exist? */
- DEFUN ("change-subwindow-property", Fchange_subwindow_property,
- Schange_subwindow_property, 3, 3, 0,
- "For the given SUBWINDOW, set PROPERTY to DATA, which is a string.")
- (subwindow, property, data)
- Lisp_Object subwindow, property, data;
- {
- Atom property_atom;
- struct Lisp_Subwindow *sw;
- Display *dpy;
-
- CHECK_SUBWINDOW (subwindow, 0);
- CHECK_STRING (property, 0);
- CHECK_STRING (data, 0);
-
- sw = XSUBWINDOW (subwindow);
- dpy = DisplayOfScreen (LISP_DEVICE_TO_X_SCREEN
- (FRAME_DEVICE (XFRAME (sw->frame))));
-
- property_atom = XInternAtom (dpy, (char *) string_data (XSTRING (property)),
- False);
- XChangeProperty (dpy, sw->subwindow, property_atom, XA_STRING, 8,
- PropModeReplace, string_data (XSTRING (data)),
- string_length (XSTRING (data)));
-
- return (property);
- }
-
- DEFUN ("subwindowp", Fsubwindowp, Ssubwindowp, 1, 1, 0,
- "Return non-nil if OBJECT is a subwindow.")
- (object)
- Lisp_Object object;
- {
- return (SUBWINDOWP (object) ? Qt : Qnil);
- }
-
- DEFUN ("subwindow-width", Fsubwindow_width, Ssubwindow_width,
- 1, 1, 0,
- "Width of SUBWINDOW.")
- (subwindow)
- Lisp_Object subwindow;
- {
- CHECK_SUBWINDOW (subwindow, 0);
- return (make_number (XSUBWINDOW (subwindow)->width));
- }
-
- DEFUN ("subwindow-height", Fsubwindow_height, Ssubwindow_height,
- 1, 1, 0,
- "Height of SUBWINDOW.")
- (subwindow)
- Lisp_Object subwindow;
- {
- CHECK_SUBWINDOW (subwindow, 0);
- return (make_number (XSUBWINDOW (subwindow)->height));
- }
-
- DEFUN ("subwindow-xid", Fsubwindow_xid, Ssubwindow_xid, 1, 1, 0,
- "Return the xid of SUBWINDOW as a number.")
- (subwindow)
- Lisp_Object subwindow;
- {
- CHECK_SUBWINDOW (subwindow, 0);
- return (make_number (XSUBWINDOW (subwindow)->subwindow));
- }
-
- DEFUN ("resize-subwindow", Fresize_subwindow, Sresize_subwindow,
- 1, 3, 0,
- "Resize SUBWINDOW to WIDTH x HEIGHT.\n\
- If a value is nil that parameter is not changed.")
- (subwindow, width, height)
- Lisp_Object subwindow, width, height;
- {
- int neww, newh;
- struct Lisp_Subwindow *sw;
-
- CHECK_SUBWINDOW (subwindow, 0);
- sw = XSUBWINDOW (subwindow);
-
- if (NILP (width))
- neww = sw->width;
- else
- neww = XINT (width);
-
- if (NILP (height))
- newh = sw->height;
- else
- newh = XINT (height);
-
- XResizeWindow (DisplayOfScreen (sw->xscreen), sw->subwindow, neww, newh);
-
- sw->height = newh;
- sw->width = neww;
-
- return subwindow;
- }
-
- DEFUN ("force-subwindow-map", Fforce_subwindow_map,
- Sforce_subwindow_map, 1, 1, 0,
- "Generate a Map event for SUBWINDOW.")
- (subwindow)
- Lisp_Object subwindow;
- {
- CHECK_SUBWINDOW (subwindow, 0);
-
- XMapWindow (DisplayOfScreen (XSUBWINDOW (subwindow)->xscreen),
- XSUBWINDOW (subwindow)->subwindow);
-
- return subwindow;
- }
-
-
- /************************************************************************/
- /* initialization */
- /************************************************************************/
-
- void
- syms_of_glyphs_x (void)
- {
- defsymbol (&Qcursorp, "cursorp");
- defsubr (&Smake_cursor);
- defsubr (&Scursorp);
- defsubr (&Scursor_name);
- defsubr (&Scursor_foreground);
- defsubr (&Scursor_background);
-
- defsubr (&Scolorize_image_instance);
-
- defsymbol (&Qsubwindowp, "subwindowp");
- defsubr (&Smake_subwindow);
- defsubr (&Schange_subwindow_property);
- defsubr (&Ssubwindowp);
- defsubr (&Ssubwindow_width);
- defsubr (&Ssubwindow_height);
- defsubr (&Ssubwindow_xid);
- defsubr (&Sresize_subwindow);
- defsubr (&Sforce_subwindow_map);
-
- defkeyword (&Q_mask_file, ":mask-file");
- defkeyword (&Q_mask_data, ":mask-data");
- defkeyword (&Q_hotspot_x, ":hotspot-x");
- defkeyword (&Q_hotspot_y, ":hotspot-y");
- defkeyword (&Q_foreground, ":foreground");
- defkeyword (&Q_background, ":background");
-
- #ifdef HAVE_XPM
- defkeyword (&Q_color_symbols, ":color-symbols");
- #endif
- }
-
- void
- device_type_create_glyphs_x (void)
- {
- /* image methods */
-
- DEVICE_HAS_METHOD (x, print_image_instance);
- DEVICE_HAS_METHOD (x, finalize_image_instance);
- DEVICE_HAS_METHOD (x, image_instance_equal);
- DEVICE_HAS_METHOD (x, image_instance_hash);
- }
-
- void
- image_instantiator_type_create_glyphs_x (void)
- {
- /* image-instantiator types */
-
- INITIALIZE_IMAGE_INSTANTIATOR_TYPE (xbm, "xbm");
-
- IITYPE_HAS_METHOD (xbm, validate);
- IITYPE_HAS_METHOD (xbm, normalize);
- IITYPE_HAS_METHOD (xbm, instantiate);
-
- IITYPE_VALID_KEYWORD (xbm, Q_data, valid_xbm_inline_p);
- IITYPE_VALID_KEYWORD (xbm, Q_file, valid_string_p);
- IITYPE_VALID_KEYWORD (xbm, Q_mask_data, valid_xbm_inline_p);
- IITYPE_VALID_KEYWORD (xbm, Q_mask_file, valid_string_p);
- IITYPE_VALID_KEYWORD (xbm, Q_hotspot_x, valid_int_p);
- IITYPE_VALID_KEYWORD (xbm, Q_hotspot_y, valid_int_p);
- IITYPE_VALID_KEYWORD (xbm, Q_foreground, valid_string_p);
- IITYPE_VALID_KEYWORD (xbm, Q_background, valid_string_p);
-
- #ifdef HAVE_JPEG
- INITIALIZE_IMAGE_INSTANTIATOR_TYPE (jpeg, "jpeg");
-
- IITYPE_HAS_METHOD (jpeg, validate);
- IITYPE_HAS_METHOD (jpeg, normalize);
- IITYPE_HAS_METHOD (jpeg, instantiate);
-
- IITYPE_VALID_KEYWORD (jpeg, Q_data, valid_string_p);
- IITYPE_VALID_KEYWORD (jpeg, Q_file, valid_string_p);
- #endif
-
- #ifdef HAVE_GIF
- INITIALIZE_IMAGE_INSTANTIATOR_TYPE (gif, "gif");
-
- IITYPE_HAS_METHOD (gif, validate);
- IITYPE_HAS_METHOD (gif, normalize);
- IITYPE_HAS_METHOD (gif, instantiate);
-
- IITYPE_VALID_KEYWORD (gif, Q_data, valid_string_p);
- IITYPE_VALID_KEYWORD (gif, Q_file, valid_string_p);
- #endif
-
- #ifdef HAVE_PNG
- INITIALIZE_IMAGE_INSTANTIATOR_TYPE (png, "png");
-
- IITYPE_HAS_METHOD (png, validate);
- IITYPE_HAS_METHOD (png, normalize);
- IITYPE_HAS_METHOD (png, instantiate);
-
- IITYPE_VALID_KEYWORD (png, Q_data, valid_string_p);
- IITYPE_VALID_KEYWORD (png, Q_file, valid_string_p);
- #endif
-
- #ifdef HAVE_XPM
- INITIALIZE_IMAGE_INSTANTIATOR_TYPE (xpm, "xpm");
-
- IITYPE_HAS_METHOD (xpm, validate);
- IITYPE_HAS_METHOD (xpm, normalize);
- IITYPE_HAS_METHOD (xpm, instantiate);
-
- IITYPE_VALID_KEYWORD (xpm, Q_data, valid_string_p);
- IITYPE_VALID_KEYWORD (xpm, Q_file, valid_string_p);
- IITYPE_VALID_KEYWORD (xpm, Q_color_symbols, valid_xpm_color_symbols_p);
- #endif
-
- #ifdef HAVE_XFACE
- INITIALIZE_IMAGE_INSTANTIATOR_TYPE (xface, "xface");
-
- IITYPE_HAS_METHOD (xface, validate);
- IITYPE_HAS_METHOD (xface, normalize);
- IITYPE_HAS_METHOD (xface, instantiate);
-
- IITYPE_VALID_KEYWORD (xface, Q_data, valid_string_p);
- IITYPE_VALID_KEYWORD (xface, Q_file, valid_string_p);
- IITYPE_VALID_KEYWORD (xface, Q_hotspot_x, valid_int_p);
- IITYPE_VALID_KEYWORD (xface, Q_hotspot_y, valid_int_p);
- IITYPE_VALID_KEYWORD (xface, Q_foreground, valid_string_p);
- IITYPE_VALID_KEYWORD (xface, Q_background, valid_string_p);
- #endif
-
- INITIALIZE_IMAGE_INSTANTIATOR_TYPE (autodetect, "autodetect");
-
- IITYPE_HAS_METHOD (autodetect, validate);
- IITYPE_HAS_METHOD (autodetect, normalize);
- IITYPE_HAS_METHOD (autodetect, instantiate);
-
- IITYPE_VALID_KEYWORD (autodetect, Q_data, valid_string_p);
- }
-
- void
- vars_of_glyphs_x (void)
- {
- #ifdef HAVE_JPEG
- Fprovide (Qjpeg);
- #endif
-
- #ifdef HAVE_GIF
- Fprovide (Qgif);
- #endif
-
- #ifdef HAVE_PNG
- Fprovide (Qpng);
- #endif
-
- #ifdef HAVE_XPM
- Fprovide (Qxpm);
-
- DEFVAR_LISP ("xpm-color-symbols", &Vxpm_color_symbols,
- "Definitions of logical color-names used when reading XPM files.\n\
- Elements of this list should be of the form (COLOR-NAME FORM-TO-EVALUATE).\n\
- The COLOR-NAME should be a string, which is the name of the color to define;\n\
- the FORM should evaluate to a `color' specifier object, or a string to be\n\
- passed to `make-color-instance'. If a loaded XPM file references a symbolic\n\
- color called COLOR-NAME, it will display as the computed color instead.\n\
- \n\
- The default value of this variable defines the logical color names\n\
- \"foreground\" and \"background\" to be the colors of the `default' face.");
- Vxpm_color_symbols = Qnil; /* initialized in x-faces.el */
- #endif
-
- #ifdef HAVE_XFACE
- Fprovide (Qxface);
- #endif
-
- DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path,
- "A list of the directories in which X bitmap files may be found.\n\
- If nil, this is initialized from the \"*bitmapFilePath\" resource.\n\
- This is used by the `make-image-instance' function (however, note that if\n\
- the environment variable XBMLANGPATH is set, it is consulted first).");
- Vx_bitmap_file_path = Qnil;
- }
-
- void
- complex_vars_of_glyphs_x (void)
- {
- #define BUILD_GLYPH_INST(variable, name) \
- Fadd_spec_to_specifier \
- (GLYPH_IMAGE (XGLYPH (variable)), \
- vector3 (Qxbm, Q_data, \
- list3 (make_number (name##_width), \
- make_number (name##_height), \
- make_ext_string ((char *) name##_bits, \
- sizeof (name##_bits)))), \
- Qglobal, Qx, Qnil)
-
- BUILD_GLYPH_INST (Vtruncation_glyph, truncator);
- BUILD_GLYPH_INST (Vcontinuation_glyph, continuer);
- BUILD_GLYPH_INST (Vxemacs_logo, xemacs);
-
- #undef BUILD_GLYPH_INST
- }
-
-